package top.lingkang.webssh.ws;

import lombok.extern.slf4j.Slf4j;
import org.noear.snack.ONode;
import org.noear.socketd.transport.core.Message;
import org.noear.socketd.transport.core.Session;
import org.noear.socketd.transport.core.entity.EntityDefault;
import org.noear.socketd.transport.core.listener.SimpleListener;

import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

/**
 * @author lingkang
 * @create by 2024/3/19 17:08
 */
@Slf4j
public class WsSimpleListener extends SimpleListener {
    private Map<String, WebTerminal> terminalMap = new HashMap<>();

    public WsSimpleListener() {
        Runtime.getRuntime().addShutdownHook(new Thread(() -> {
            for (Map.Entry<String, WebTerminal> entry : terminalMap.entrySet())
                entry.getValue().onTerminalClose();
            log.info("关闭所有ws，关闭数量：{}", terminalMap.size());
        }));
    }

    @Override
    public void onOpen(Session session) throws IOException {
        Object id = session.param("id");
        if (id == null) {
            log.warn("无id的连接，关闭会话：{}", session.sessionId());
            session.close();
        }
    }

    @Override
    public void onMessage(Session session, Message message) throws IOException {
        String type = message.meta("type");
        if (type != null) {
            String data = message.entity().dataAsString();
            if ("cmd".equals(type)) {
                WebTerminal terminal = terminalMap.get(session.sessionId());
                terminal.command(data);
            } else if ("resize".equals(type)) {
                ONode node = ONode.loadStr(data);
                WebTerminal terminal = terminalMap.get(session.sessionId());
                terminal.resize(node.get("columns").getString(), node.get("rows").getString());
            } else if ("init".equals(type)) {
                ONode node = ONode.loadStr(data);
                WebTerminal terminal = new WebTerminal(
                        session,
                        node.select("$.columns").getString(),
                        node.select("$.rows").getString());
                terminalMap.put(session.sessionId(), terminal);
            } else if ("ping".equals(type)) {
                EntityDefault entityDefault = new EntityDefault();
                entityDefault.dataSet(message.data());
                entityDefault.metaPut("type", "pong");
                session.send("/", entityDefault);
            }
        }
    }

    @Override
    public void onClose(Session session) {
        WebTerminal terminal = terminalMap.remove(session.sessionId());
        if (terminal != null)
            terminal.onTerminalClose();
    }

    @Override
    public void onError(Session session, Throwable error) {
        log.warn("onError {}", session.sessionId(), error);
    }
}
